﻿// ------------------------------------------------------------------------
// Copyright 2021 The Dapr Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//     http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------

using System.Collections.Generic;
using System.Threading.Tasks;
using Autogenerated = Dapr.Client.Autogen.Grpc.v1;
using Xunit;
using Shouldly;

namespace Dapr.Client.Test;

public class ConfigurationApiTest
{
    [Fact]
    public async Task GetConfigurationAsync_WithAllValues_ValidateRequest()
    {
        await using var client = TestClient.CreateForDaprClient();
        var metadata = new Dictionary<string, string>
        {
            { "key1", "value1" },
            { "key2", "value2" }
        };
        var request = await client.CaptureGrpcRequestAsync(async daprClient =>
        {
            return await daprClient.GetConfiguration("testStore", new List<string>() { "test_key" }, metadata);
        });

        // Get Request and validate
        var envelope = await request.GetRequestEnvelopeAsync<Autogenerated.GetConfigurationRequest>();
        envelope.StoreName.ShouldBe("testStore");
        envelope.Keys.ShouldContain("test_key");
        envelope.Metadata.Count.ShouldBe(2);
        envelope.Metadata.Keys.Contains("key1").ShouldBeTrue();
        envelope.Metadata.Keys.Contains("key2").ShouldBeTrue();
        envelope.Metadata["key1"].ShouldBe("value1");
        envelope.Metadata["key2"].ShouldBe("value2");

        // Get response and validate
        var invokeResponse = new Autogenerated.GetConfigurationResponse();
        invokeResponse.Items["testKey"] = new Autogenerated.ConfigurationItem()
        {
            Value = "testValue",
            Version = "v1"
        };

        var domainResponse = await request.CompleteWithMessageAsync(invokeResponse);
        var configItem = domainResponse.Items["testKey"];
        configItem.Value.ShouldBe("testValue");
        configItem.Version.ShouldBe("v1");
    }

    [Fact]
    public async Task GetConfigurationAsync_WithNullKeys_ValidateRequest()
    {
        await using var client = TestClient.CreateForDaprClient();
        var metadata = new Dictionary<string, string>
        {
            { "key1", "value1" },
            { "key2", "value2" }
        };
        var request = await client.CaptureGrpcRequestAsync(async daprClient =>
        {
            return await daprClient.GetConfiguration("testStore", null, metadata);
        });

        // Get Request and validate
        var envelope = await request.GetRequestEnvelopeAsync<Autogenerated.GetConfigurationRequest>();
        envelope.StoreName.ShouldBe("testStore");
        envelope.Keys.ShouldBeEmpty();
        envelope.Metadata.Count.ShouldBe(2);
        envelope.Metadata.Keys.Contains("key1").ShouldBeTrue();
        envelope.Metadata.Keys.Contains("key2").ShouldBeTrue();
        envelope.Metadata["key1"].ShouldBe("value1");
        envelope.Metadata["key2"].ShouldBe("value2");

        // Get response and validate
        var invokeResponse = new Autogenerated.GetConfigurationResponse();
        invokeResponse.Items["testKey"] = new Autogenerated.ConfigurationItem()
        {
            Value = "testValue",
            Version = "v1"
        };

        var domainResponse = await request.CompleteWithMessageAsync(invokeResponse);
        var configItem = domainResponse.Items["testKey"];
        configItem.Value.ShouldBe("testValue");
        configItem.Version.ShouldBe("v1");
    }

    [Fact]
    public async Task GetConfigurationAsync_WithNullMetadata_ValidateRequest()
    {
        await using var client = TestClient.CreateForDaprClient();
        var request = await client.CaptureGrpcRequestAsync(async daprClient =>
        {
            return await daprClient.GetConfiguration("testStore", new List<string>() { "test_key" });
        });

        // Get Request and validate
        var envelope = await request.GetRequestEnvelopeAsync<Autogenerated.GetConfigurationRequest>();
        envelope.StoreName.ShouldBe("testStore");
        envelope.Keys.ShouldContain("test_key");
        envelope.Metadata.Count.ShouldBe(0);

        // Get response and validate
        var invokeResponse = new Autogenerated.GetConfigurationResponse();
        invokeResponse.Items["testKey"] = new Autogenerated.ConfigurationItem()
        {
            Value = "testValue",
            Version = "v1"
        };

        var domainResponse = await request.CompleteWithMessageAsync(invokeResponse);
        var configItem = domainResponse.Items["testKey"];
        configItem.Value.ShouldBe("testValue");
        configItem.Version.ShouldBe("v1");
    }

    [Fact]
    public async Task UnsubscribeConfiguration_ValidateRequest()
    {
        await using var client = TestClient.CreateForDaprClient();
        var request = await client.CaptureGrpcRequestAsync(async daprClient =>
        {
            return await daprClient.UnsubscribeConfiguration("testStore", "testId");
        });

        var envelope = await request.GetRequestEnvelopeAsync<Autogenerated.UnsubscribeConfigurationRequest>();
        envelope.StoreName.ShouldBe("testStore");
        envelope.Id.ShouldBe("testId");
        request.Dismiss();
    }
}